#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cassert>
#include <functional>
#include <pthread.h>

class Thread;

class Context
{
public:
    Context()
    :_this(nullptr)
    ,_args(nullptr)
    {}
    ~Context()
    {}
public:
    Thread* _this;
    void* _agrs;
};

class Thread
{
public:
    typdef std::function<void*(void*)> func_t;
    const int num = 1024;
public:
        Thread(func_t func, void* agrs = nullptr, int number = 0)
        :_func(func)
        ,args(_args)
        {
            char buffer[num];
            snprintf(bufferm sizeof(buffer), "thread-%d", number);
            _name = buffer;
            Context* ctx = new Context();
            ctx->_this; = this;
            ctx->_args = _agrs;
            int n = pthread_create(&_tid, nullptr, static_routine, ctx);
            assert(n == 0);
            (void)n;
        }
        static void* static_routine(void* agrs)
        {
            Context* ctx = static_cast<Context*>(args);
            void* ret = ctx->_this->run(ctx->_args);
            delete ctx;
            return ret;
        }
        void join()
        {
            int n = pthread_join(_tid, nullptr);
            assert(n == 0);
            (void)n;
        }
        void* run(void* agrs)
        {
            return _func(args);
        }
        ~Thread()
        {}
private:
    std::string _name;
    func_t _func;
    void* _args;
    pthread_t _tid;
};